#include <mpi.h>
#include <iostream>
#include <cstdlib>
#include <sys/time.h>
#include <cmath>
#include <omp.h>
#include <pmmintrin.h>
#include <vector>
using namespace std;

extern int n, thread_count;
extern float **A;
void recycle_bcast_nonblock_gauss(int my_rank, int num_proc) {
    MPI_Request *r_send = new MPI_Request[num_proc - 1];
    MPI_Request r_recv;
    MPI_Status s_send, s_recv;   
    for (int k = 0; k < n; k++) {
        if (k % num_proc == my_rank) {
            float ele = A[k][k];
            for (int j = k + 1; j < n; j++)
                A[k][j] = A[k][j] / ele;
            A[k][k] = 1.0;
            for (int j = 0; j < num_proc; j++)
                if (j != my_rank)
                    MPI_Isend(A[k], n, MPI_FLOAT, j, 2, MPI_COMM_WORLD, r_send + j);
        }
        else {
            int current_work_p = k % num_proc;
            MPI_Irecv(A[k], n, MPI_FLOAT, current_work_p, 2, MPI_COMM_WORLD, &r_recv);
            MPI_Wait(&r_recv, &s_recv);
        }
        for (int i = my_rank; i < n; i += num_proc) {
            if (i > k) {
                for (int j = k + 1; j < n; j++){
                    A[i][j] = A[i][j] - A[i][k] * A[k][j]; 
                }
                A[i][k] = 0.0;
            }
        }
        if (k % num_proc != my_rank) 
            continue;
        for (int j = 0; j < num_proc; j++)
            if (j != my_rank)
                MPI_Wait(r_send + j, &s_send);
    }
}
